#include "Thread.h"

Thread::Thread(thread_func func, const char *name, void *lpara)
{
	m_threadFunc = func;
	m_lPara = lpara;
	strcpy(m_name, name);
    tid = -1;
    m_created = false;
    m_joined = false;
}

Thread::~Thread()
{
	if (!m_joined)
		wait();
}

void *Thread::s_thread_func(void *lpara) 
{
	Thread *pThread = static_cast<Thread *>(lpara);
	LOGI("Thread:Run %s[%lu]", pThread->m_name, gettid());
	pthread_setname_np(pthread_self(), pThread->m_name);
    pThread->tid = gettid();
	pThread->m_retval = pThread->m_threadFunc(pThread->m_lPara);
    LOGI("Thread:Exit %s[%lu]", pThread->m_name, gettid());

	return NULL;
}

bool Thread::start()
{
	m_retval = pthread_create(&m_tid, NULL, s_thread_func, this);
	if(m_retval) 
		return false;
    m_created = true;
    m_joined = false;
	return true;
}

bool Thread::setThreadPriority(ThreadPriority priority)
{
    if (!m_created)
        return true;
    struct sched_param sched;
    int policy;
    pthread_t thread = pthread_self();

    if (pthread_getschedparam(thread, &policy, &sched) < 0) {
        LOGE("pthread_getschedparam() failed");
        return false;
    }
    if (priority == THREAD_PRIORITY_LOW) {
        sched.sched_priority = sched_get_priority_min(policy);
    } else if (priority == THREAD_PRIORITY_HIGH) {
        sched.sched_priority = sched_get_priority_max(policy);
    } else {
        int min_priority = sched_get_priority_min(policy);
        int max_priority = sched_get_priority_max(policy);
        sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
    }
    if (pthread_setschedparam(thread, policy, &sched) < 0) {
        LOGE("pthread_setschedparam() failed");
        return false;
    }
    return true;
}

void Thread::wait(int *status)
{
    if (!m_created)
        return;
    pthread_join(m_tid, NULL);
    m_joined = true;
    if (status)
    	*status = m_retval;
}

void Thread::detach()
{
    if (!m_created)
        return;
    pthread_detach(m_tid);
}

bool Thread::isExited()
{
    return m_joined;
}